package me.lwn.auth.application;

import me.lwn.auth.security.oauth2.server.authorization.JdbcServerSettingRepository;
import me.lwn.auth.security.oauth2.server.authorization.ServerSetting;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.ConfigurationSettingNames;
import org.springframework.stereotype.Service;

import java.util.List;

import static me.lwn.auth.security.utils.Constants.SPRING_SECURITY_FORM_REQUIRE_CAPTCHA;

@Service
public class ServerSettingManager {

    private static final String REGISTERED_CLIENT_TABLE_NAME = "oauth2_registered_client";
    private static final String LOAD_REGISTERED_CLIENT_SQL = "SELECT id, token_settings FROM " + REGISTERED_CLIENT_TABLE_NAME;
    private final JdbcTemplate jdbcTemplate;
    private final JdbcServerSettingRepository repository;
    private final RegisteredClientRepository registeredClientRepository;
    private final RowMapper<RegisteredClient> registeredClientRowMapper;

    public ServerSettingManager(JdbcTemplate jdbcTemplate, JdbcServerSettingRepository repository, RegisteredClientRepository registeredClientRepository) {
        this.jdbcTemplate = jdbcTemplate;
        this.repository = repository;
        this.registeredClientRepository = registeredClientRepository;
        this.registeredClientRowMapper = new JdbcRegisteredClientRepository.RegisteredClientRowMapper();
    }

    public ServerSetting save(ServerSetting serverSetting) {

        repository.save(serverSetting);

        List<RegisteredClient> registeredClients = findAllRegisteredClient();
        registeredClients.forEach(registeredClient -> {
            if (serverSetting.isGlobalTokenSetting()) {
                registeredClient.getTokenSettings().getSettings().put(ConfigurationSettingNames.Token.ACCESS_TOKEN_TIME_TO_LIVE, serverSetting.getAccessTokenTimeToLive());
                registeredClient.getTokenSettings().getSettings().put(ConfigurationSettingNames.Token.REFRESH_TOKEN_TIME_TO_LIVE, serverSetting.getRefreshTokenTimeToLive());
            }
            if (serverSetting.isGlobalClientSetting()) {
                registeredClient.getClientSettings().getSettings().put(SPRING_SECURITY_FORM_REQUIRE_CAPTCHA, serverSetting.isRequireCaptcha());
            }
            registeredClientRepository.save(registeredClient);
        });
        return repository.get();
    }

    public ServerSetting get() {
        return repository.get();
    }

    private List<RegisteredClient> findAllRegisteredClient() {
        return this.jdbcTemplate.query(
                LOAD_REGISTERED_CLIENT_SQL, this.registeredClientRowMapper);
    }
}
